#include "objToIsm1.h"
void objToIsm1(char* in,char *out,char* option)
{
	arrayVec3 vertices;
	arrayVec2 texcoords;
	arrayVec3 normals;
	arrayVec3 faces;
	char line[200];
	ifstream fin(in);

	vector<string> options;
	QUALITY q = QUALITY_LOW;
	if(option)
	{
		split(string(option), options,';');
		for(int i=0;i<options.size();i++)
		{
			if( options[i].compare("hq"))
				q = QUALITY_HIGH;
			else
			{
				cout<<"Error: Invalid option :"<<options[i];
				return;
			}
		}
	}
	if(fin.good())
	{
		cout<<"\nStart read obj file..";
		while(!fin.eof())
		{
			vector<string> atts;
			fin.getline(line,199);
			split(string(line), atts,' ');
			if( !atts[0].compare("v") ) // vertices
			{
				vertices.push_back( gewVec3( stof(atts[1]),stof(atts[2]),stof(atts[3])));
			}
			if( !atts[0].compare("vn") ) // normals
			{
				gewVec3 raw_normal(stof(atts[1]),stof(atts[2]),stof(atts[3]));
				raw_normal.normalize();
				normals.push_back(raw_normal);
			}
			if( !atts[0].compare("vt") ) // texcoords
			{
				texcoords.push_back( gewVec2( stof(atts[1]),stof(atts[2])));
			}
			if( !atts[0].compare("f") ) // face, auto triangulate the face as triangle fan
			{
				gewVec3 pre;
				vector<string> face_atts;
				for (int i=1; i<atts.size(); i++) 
				{
					if (i > 3)
					{
						face_atts.clear();
						split(atts[1],face_atts,'/');
						gewVec3 fan_center(stoi(face_atts[0]),stoi(face_atts[1]),stoi(face_atts[2]));
						faces.push_back(fan_center);
						faces.push_back(pre);
					}
					face_atts.clear();
					split(atts[i],face_atts,'/');
					pre = gewVec3( stoi(face_atts[0]),stoi(face_atts[1]),stoi(face_atts[2]));
					faces.push_back(pre);
				}
			}	
		}
		cout<<"\nFinish read obj file..";
		arrayVec3 overtices;
		arrayVec2 otexcoords;
		arrayVec3 onormals;
		vector<unsigned int> oindices;
		arrayVec3 processed;

		//Calculate bounding volume
		gewAabb boundingBox;
		gewSphere boundingSphere;

		boundingBox.minVertex = vertices[0];
		boundingBox.maxVertex = vertices[0];
		
		for(int i = 0; i < vertices.size();i++)
		{
			boundingBox.addInternalPoint(vertices[i]);
		}
		//Calculate bounding sphere 
		boundingSphere.calculate(vertices);


		cout<<"\nStart convert mesh data..";
		for(int i=0;i< faces.size();i++)
		{
			int offset = isIn(faces[i],processed);
			if(offset==-1) // new
			{
				processed.push_back( faces[i]);
				overtices.push_back( vertices[ faces[i].x-1]);
				otexcoords.push_back( texcoords[ faces[i].y-1]);
				onormals.push_back( normals[ faces[i].z-1]);
				oindices.push_back( processed.size()-1);
			}
			else
			{
				oindices.push_back( offset);
			}
		}
		cout<<"\nFinish convert mesh data..";
		cout<<"\nStart write output file..";
		FIXED_POINT_FORMAT ver_fp_format = findFixedPointFormat(overtices);
		FIXED_POINT_FORMAT tex_fp_format = findFixedPointFormat(otexcoords);
		FIXED_POINT_FORMAT nor_fp_format = findFixedPointFormat(onormals);
		if(q==QUALITY_HIGH)
		{
			ver_fp_format= FP_1_15_16;
		}
		cout<<"\nVertices Fixed point format:"<<getFixedPointStr(ver_fp_format);
		cout<<"\nTexcoords Fixed point format:"<<getFixedPointStr(tex_fp_format);
		cout<<"\nNormals Fixed point format:"<<getFixedPointStr(nor_fp_format);
		cout<<"\nVertices number:"<<overtices.size();
		cout<<"\nIndices number:"<<oindices.size();

		ofstream fout(out,ios_base::out|ios_base::binary| ios_base::trunc);
		unsigned int temp;
		// magic number
		fout<<"ism1";
		// type of this mesh : 
		//	1 : mesh that contain 3-coord per position, 2-coord per texcoord, 3-coord per normal
		fout<<char(1);
		// Vertices Fixed point format
		temp = ver_fp_format;
		fout.write((char*)(&temp),4);
		// Texcoords Fixed point format
		temp = tex_fp_format;
		fout.write((char*)(&temp),4);
		// nNormals Fixed point format
		temp = nor_fp_format;
		fout.write((char*)(&temp),4);
		// vertices count
		temp = overtices.size();
		fout.write((char*)(&temp),4);

		// LOD level number
		fout<<char(1);
		// indices length of LOD lv0
		temp = oindices.size();
		fout.write((char*)(&temp),4);
		
		fout.seekp(64,ios_base::beg);
		// writing vertices attribute 
		int byte_per_ver_coord = getFixedPointSize(ver_fp_format);
		int byte_per_tex_coord = getFixedPointSize(tex_fp_format);
		int byte_per_nor_coord = getFixedPointSize(nor_fp_format);
		for(int i=0;i<overtices.size();i++)
		{
			// position
			temp = floatToFixed( overtices[i].x, ver_fp_format);
			fout.write((char*)(&temp),byte_per_ver_coord);
			temp = floatToFixed( overtices[i].y,ver_fp_format);
			fout.write((char*)(&temp),byte_per_ver_coord);
			temp = floatToFixed( overtices[i].z,ver_fp_format);
			fout.write((char*)(&temp),byte_per_ver_coord);
			// texcoord
			temp = floatToFixed( otexcoords[i].x,tex_fp_format);
			fout.write((char*)(&temp),byte_per_tex_coord);
			temp = floatToFixed( otexcoords[i].y,tex_fp_format);
			fout.write((char*)(&temp),byte_per_tex_coord);
			// normals
			temp = floatToFixed( onormals[i].x,nor_fp_format);
			fout.write((char*)(&temp),byte_per_nor_coord);
			temp = floatToFixed( onormals[i].y,nor_fp_format);
			fout.write((char*)(&temp),byte_per_nor_coord);
			temp = floatToFixed( onormals[i].z,nor_fp_format);
			fout.write((char*)(&temp),byte_per_nor_coord);			
		}
		// writing indices
		for(int i=0;i<oindices.size();i++)
		{
			temp = oindices[i];
			fout.write((char*)(&temp),2);
		}
		// writing bounding volume
		// aabb
		temp = floatToFixed( boundingBox.minVertex.x,ver_fp_format);
		fout.write((char*)(&temp),byte_per_ver_coord);
		temp = floatToFixed( boundingBox.minVertex.y,ver_fp_format);
		fout.write((char*)(&temp),byte_per_ver_coord);
		temp = floatToFixed( boundingBox.minVertex.z,ver_fp_format);
		fout.write((char*)(&temp),byte_per_ver_coord);
		temp = floatToFixed( boundingBox.maxVertex.x,ver_fp_format);
		fout.write((char*)(&temp),byte_per_ver_coord);
		temp = floatToFixed( boundingBox.maxVertex.y,ver_fp_format);
		fout.write((char*)(&temp),byte_per_ver_coord);
		temp = floatToFixed( boundingBox.maxVertex.z,ver_fp_format);
		fout.write((char*)(&temp),byte_per_ver_coord);
		// bounding sphere
		temp = floatToFixed( boundingSphere.center.x,ver_fp_format);
		fout.write((char*)(&temp),byte_per_ver_coord);
		temp = floatToFixed( boundingSphere.center.y,ver_fp_format);
		fout.write((char*)(&temp),byte_per_ver_coord);
		temp = floatToFixed( boundingSphere.center.z,ver_fp_format);
		fout.write((char*)(&temp),byte_per_ver_coord);
		temp = floatToFixed( boundingSphere.radius,ver_fp_format);
		fout.write((char*)(&temp),byte_per_ver_coord);

		cout<<"\nFinish write output file..";
		fout.close();
		fin.close();
	}
	else
	{
		cout<<"\nError when open file :"<<in;
	}
	
}